﻿/***********************************************************************
 *            Project: CoreCms.Net                                     *
 *                Web: https://CoreCms.Net                             *
 *        ProjectName: 核心内容管理系统                                *
 *             Author: 大灰灰                                          *
 *              Email: JianWeie@163.com                                *
 *         CreateTime: 2020-10-21 21:46:04
 *        Description: 暂无
 ***********************************************************************/


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using CoreCms.Net.Caching.Manual;
using CoreCms.Net.Caching.MemoryCache;
using CoreCms.Net.Configuration;

namespace CoreCms.Net.Filter
{
    public static class AdminsControllerPermission
    {

        /// <summary>
        /// 缓存ActionPermission名称
        /// </summary>
        private const string CacheCoreCmsActionPermission = "CacheCoreCmsActionPermission";
        /// <summary>
        /// 缓存ControllerPermission名称
        /// </summary>
        private const string CacheCoreCmsControllerPermission = "CacheCoreCmsControllerPermission";


        /// <summary>
        ///     反射获取所有controller 和action
        /// </summary>
        /// <returns></returns>
        private static ControllerPermissionResult GetAllControllerAndActionByAssembly(string dataSources)
        {
            var result = new List<ControllerPermission>();

            var types = dataSources == GlobalEnumVars.CoreShopSystemCategory.Admin.ToString() ? Assembly.Load("CoreCms.Net.Web.Admin").GetTypes() :
                dataSources == GlobalEnumVars.CoreShopSystemCategory.Api.ToString() ? Assembly.Load("CoreCms.Net.Web.WebApi").GetTypes() : null;

            //var types = Assembly.Load("CoreCms.Net.Web.Admin").GetTypes();

            var noController = new[] { "ToolsController", "LoginController", "DemoController" };

            var acs = new List<ActionPermission>();

            var controllers = types.Where(p => p.Name.Contains("Controller") && !noController.Contains(p.Name));
            foreach (var type in controllers)
            {
                if (type.BaseType != null && (type.Name.Length <= 10 || type.BaseType.Name != "ControllerBase" || !type.Name.EndsWith("Controller"))) continue;

                var members = type.GetMethods();
                var cp = new ControllerPermission();
                cp.name = type.Name.Substring(0, type.Name.Length - 10);
                cp.action = new List<ActionPermission>();
                cp.controllerName = cp.name;

                var objs = type.GetCustomAttributes(typeof(DescriptionAttribute), true);
                if (objs.Length > 0) cp.description = (objs[0] as DescriptionAttribute)?.Description;
                //附加此代码用于代码生成器显示选择
                if (!string.IsNullOrEmpty(cp.description))
                {
                    cp.name += "【" + cp.description + "】";
                }

                var newMembers = members.Where(p =>
                    p.ReturnType.FullName != null && (p.ReturnType.Name == "ActionResult" ||
                                                      p.ReturnType.Name == "FileResult" ||
                                                      p.ReturnType.Name == "JsonResult" ||
                                                      (p.ReturnType.GenericTypeArguments.Length > 0 && p.ReturnType.GenericTypeArguments[0].Name == "JsonResult") ||
                                                      p.ReturnType.Name == "AdminUiCallBack" ||
                                                      p.ReturnType.Name == "IActionResult" ||
                                                      p.ReturnType.FullName.Contains("CoreCms.Net.Model.ViewModels.UI.AdminUiCallBack"))
                ).ToList();

                foreach (var member in newMembers)
                {
                    if (member.Name == "ValidationProblem" || member.Name == "Json") continue;

                    //if (member.ReturnType.Name == "ActionResult" || member.ReturnType.Name == "FileResult" || member.ReturnType.Name == "JsonResult" || (member.ReturnType.GenericTypeArguments.Length > 0 && member.ReturnType.GenericTypeArguments[0].Name == "JsonResult")) //如果是Action
                    //{
                    //}

                    var ap = new ActionPermission();
                    ap.name = member.Name;
                    ap.actionName = member.Name;
                    if (member.DeclaringType != null)
                    {
                        // 去掉“Controller”后缀
                        ap.controllerName = member.DeclaringType.Name.Substring(0, member.DeclaringType.Name.Length - 10);
                    }
                    ap.path = "/Api/" + ap.controllerName + "/" + member.Name;

                    var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), true);
                    if (attrs.Length > 0) ap.description = (attrs[0] as DescriptionAttribute)?.Description;
                    //附加此代码用于代码生成器显示选择
                    if (!string.IsNullOrEmpty(ap.description))
                    {
                        ap.name += "【" + ap.description + "】";
                    }
                    ap.controllerDescription = cp.description;

                    cp.action.Add(ap);
                    acs.Add(ap);
                }
                cp.action = cp.action.Distinct(new ModelComparer()).ToList();
                result.Add(cp);
            }

            var resultObj = new ControllerPermissionResult
            {
                ControllersAndActions = result,
                Actions = acs
            };
            return resultObj;
        }

        private class ModelComparer : IEqualityComparer<ActionPermission>
        {
            public bool Equals(ActionPermission x, ActionPermission y)
            {
                return x.name.ToUpper() == y.name.ToUpper();
            }

            public int GetHashCode(ActionPermission obj)
            {
                return obj.name.ToUpper().GetHashCode();
            }
        }

        /// <summary>
        /// 获取缓存ActionPermission
        /// </summary>
        /// <returns></returns>
        public static List<ActionPermission> GetCacheCoreCmsActionPermission(string dataSources)
        {
            var memoryCacheManager = new MemoryCacheManager();
            var cache = memoryCacheManager.Get<List<ActionPermission>>(CacheCoreCmsActionPermission);
            return cache ?? UpdateCacheCoreCmsActionPermission(dataSources).Actions;
        }

        /// <summary>
        /// 获取缓存ControllerPermission名称
        /// </summary>
        /// <returns></returns>
        public static List<ControllerPermission> GetCacheCoreCmsControllerPermission(string dataSources)
        {
            var memoryCacheManager = new MemoryCacheManager();
            var cache = memoryCacheManager.Get<List<ControllerPermission>>(CacheCoreCmsControllerPermission);
            return cache ?? UpdateCacheCoreCmsActionPermission(dataSources).ControllersAndActions;
        }

        /// <summary>
        ///     更新cache
        /// </summary>
        private static ControllerPermissionResult UpdateCacheCoreCmsActionPermission(string dataSources)
        {
            var list = GetAllControllerAndActionByAssembly(dataSources);
            var memoryCacheManager = new MemoryCacheManager();
            //缓存24小时
            memoryCacheManager.Set(CacheCoreCmsControllerPermission, list.ControllersAndActions, 1440);
            memoryCacheManager.Set(CacheCoreCmsActionPermission, list.Actions, 1440);
            return list;
        }
    }


    /// <summary>
    /// 外部包一圈
    /// </summary>
    public class ControllerPermissionResult
    {
        /// <summary>
        /// 实际结果集
        /// </summary>
        public List<ControllerPermission> ControllersAndActions { get; set; }

        /// <summary>
        /// 只获取的action集合，用于缓存
        /// </summary>
        public List<ActionPermission> Actions { get; set; }

    }

    /// <summary>
    /// action数据
    /// </summary>
    public sealed class ActionPermission
    {
        /// <summary>
        ///     地址
        /// </summary>
        public string path { get; set; }

        /// <summary>
        ///     地址及描述
        /// </summary>
        public string name { get; set; }

        /// <summary>
        ///     控制器
        /// </summary>
        public string controllerName { get; set; }

        /// <summary>
        ///     控制器描述
        /// </summary>
        public string controllerDescription { get; set; }

        /// <summary>
        ///     方法
        /// </summary>
        public string actionName { get; set; }

        /// <summary>
        ///     描述
        /// </summary>
        public string description { get; set; }

        /// <summary>
        ///     类型
        /// </summary>
        public string type { get; set; } = "action";

    }

    /// <summary>
    /// Controller数据
    /// </summary>
    public sealed class ControllerPermission
    {
        /// <summary>
        /// 控制器
        /// </summary>
        public string controllerName { get; set; }

        /// <summary>
        /// 控制器和描述
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string description { get; set; }

        /// <summary>
        /// 方法列表
        /// </summary>
        public IList<ActionPermission> action { get; set; }

        /// <summary>
        /// 类型
        /// </summary>
        public string type { get; set; } = "controller";

    }
}
